package jkCore.social;

import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;

import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.ProductDetails;
import com.android.billingclient.api.ProductDetailsResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchaseHistoryRecord;
import com.android.billingclient.api.PurchaseHistoryResponseListener;
import com.android.billingclient.api.PurchasesResponseListener;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.QueryProductDetailsParams;
import com.android.billingclient.api.QueryPurchaseHistoryParams;
import com.android.billingclient.api.QueryPurchasesParams;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.tendcloud.tenddata.TalkingDataGender;
import com.tendcloud.tenddata.TalkingDataProfile;
import com.tendcloud.tenddata.TalkingDataProfileType;
import com.tendcloud.tenddata.TalkingDataSDK;

import org.cocos2dx.javascript.AppActivity;
import org.cocos2dx.javascript.service.SDKClass;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import jkCore.social.ad.AdManager;
import jkCore.social.ad.adapter.MAXAdapter;
import jkCore.utils.Utils;

public class SocialManager extends SDKClass {
    private static String TAG = "SocialManager";
    private static SocialManager instance;
    private static Context mContext;
    private static int onQueryPurchasesResponseCnt;
    private AppActivity mActivity;

    private static TalkingDataProfile mTalkingDataProfile;
    private static FirebaseAnalytics mFirebaseAnalytics;
    private static FirebaseRemoteConfig mFirebaseRemoteConfig;
    private static BillingClient mBillingClient;
    private static Handler mHandler = new Handler();
    private static int reTryDelayTime = 5 * 1000;
    private static boolean isDownloadingUrl;

    @Override
    public void init(Context context) {
        super.init(context);
        Log.d(TAG, String.format("init"));

        instance = this;
        mContext = context;
        mActivity = (AppActivity) mContext;

        initFirebaseAnalytics(mActivity);
        initFireBaseRemoteConfig();
    }

    @Override
    public void setGLSurfaceView(GLSurfaceView view) {
        super.setGLSurfaceView(view);
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d(TAG, String.format("onActivityResult requestCode = %s resultCode = %s data = %s", requestCode, resultCode, data));
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        Log.d(TAG, String.format("onRequestPermissionsResult requestCode = %s permissions = %s grantResults = %s", requestCode, permissions, grantResults));
    }

    @Override
    public void onNewIntent(Intent intent) {
    }

    @Override
    public void onRestart() {
    }

    @Override
    public void onStop() {
    }

    @Override
    public void onBackPressed() {
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
    }

    @Override
    public void onStart() {
    }

    @Override
    public void onKeyDown(int keyCode, KeyEvent event) {

    }

// ============================================================================================
// =====================================   内部方法   ===========================================
// ============================================================================================

// ============================================================================================
// =====================================   外部方法   ===========================================
// ============================================================================================

// ============================================================================================
// =====================================   静态方法   ===========================================
// ============================================================================================

    public static void initWithApplication(Context appContext) {
        Log.d(TAG, "init");

        initTalkingData(appContext);
    }

    /**
     * 发送邮件
     *
     * @param desAddress 收件人
     * @param subject    主题名称
     * @param uuid       设备唯一识别
     */
    public static void sendEmail(final String desAddress, final String subject, final String uuid) {
        Log.d(TAG, String.format("sendEmail desAddress = %s subject = %s uuid = %s", desAddress, subject, uuid));

        try {
            String mobileName = Build.BRAND;
            String sysVersion = android.os.Build.VERSION.SDK_INT + "";
            Intent it = new Intent(Intent.ACTION_SEND);
            it.putExtra(Intent.EXTRA_EMAIL, new String[]{desAddress});
            it.setType("*/*");
            if (!TextUtils.isEmpty(subject)) {
                it.putExtra(Intent.EXTRA_SUBJECT, subject);
            }
            //正文
            JSONObject content = new JSONObject();
            try {
                content.put("mobileName", mobileName);
                content.put("uuid", uuid);
                content.put("sysVersion", sysVersion);
                it.putExtra(Intent.EXTRA_TEXT, content.toString());
            } catch (Exception e) {
                Log.e("BaseUtil", "邮件参数数据");
            }
            mContext.startActivity(createEmailOnlyChooserIntent(it, desAddress, "请选择邮件类应用"));
        } catch (Exception e) {
            Log.e("sendEmail", e.toString());
        }
    }

    /**
     * 使用匹配器寻找合适的邮件发送者
     *
     * @param source
     * @param receiver     收件人
     * @param chooserTitle
     * @return
     */
    private static Intent createEmailOnlyChooserIntent(Intent source, String receiver, String chooserTitle) {
        Log.d(TAG, String.format("createEmailOnlyChooserIntent receiver = %s chooserTitle = %s", receiver, chooserTitle));

        Stack<Intent> intents = new Stack<>();
        Intent i = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + receiver));
        List<ResolveInfo> activities = mContext.getPackageManager().queryIntentActivities(i, 0);
        for (ResolveInfo ri : activities) {
            Intent target = new Intent(source);
            target.setPackage(ri.activityInfo.packageName);
            intents.add(target);
        }
        if (!intents.isEmpty()) {
            Intent chooserIntent = Intent.createChooser(intents.remove(0), chooserTitle);
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new Parcelable[0]));

            return chooserIntent;
        } else {
            return Intent.createChooser(source, chooserTitle);
        }
    }

    /**
     * 分享App
     *
     * @param shareMsg
     */
    public static void shareApp(String shareMsg) {
        Log.d(TAG, String.format("shareApp shareMsg = %s", shareMsg));

        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_TEXT, shareMsg);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setType("text/plain");
        mContext.startActivity(Intent.createChooser(intent, "Share App"));
    }

    /**
     * 分享本地或远程资源到第三方应用
     *
     * @param resUrl   资源地址
     * @param shareMsg 文本
     */
    public static void shareRes(String resUrl, final String shareMsg) {
        Log.d(TAG, String.format("shareRes resUrl = %s", resUrl));

        //资源地址为空时默认用纯文字分享
        if (TextUtils.isEmpty(resUrl)) {
            //如果確定发纯文字短信
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            //彩信发送目的号码
            intent.putExtra("address", "");
            //彩信中文字内容
            intent.putExtra("sms_body", shareMsg);
            mContext.startActivity(intent);
        } else {
            if (resUrl.startsWith("http")) {
                shareRemoteRes(resUrl, shareMsg);
            } else {
                shareLocalRes(resUrl, shareMsg, "");
            }
        }
    }

    /**
     * 分享远程资源到第三方应用
     *
     * @param resUrl   资源地址
     * @param shareMsg 文本
     */
    private static void shareRemoteRes(final String resUrl, String shareMsg) {
        Log.d(TAG, String.format("shareRemoteRes resUrl = %s shareMsg = %s", resUrl, shareMsg));

        new Thread(new Runnable() {
            @Override
            public void run() {
                URL url;
                Bitmap bitmap;
                try {
                    url = new URL(resUrl);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    //超时设置
                    connection.setConnectTimeout(10 * 1000);
                    connection.setDoInput(true);
                    //设置不使用缓存
                    connection.setUseCaches(false);
                    InputStream inputStream = connection.getInputStream();
                    bitmap = BitmapFactory.decodeStream(inputStream);
                    inputStream.close();
                    connection.disconnect();
                    File file = new File(mContext.getCacheDir().toString());
                    FileOutputStream fileOutputStream;
                    //文件夹不存在，则创建它
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                    String fileName = file.toString() + "/" + System.currentTimeMillis() + ".png";
                    fileOutputStream = new FileOutputStream(fileName);
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
                    fileOutputStream.close();
                    //其次把文件插入到系统图库
                    MediaStore.Images.Media.insertImage(mContext.getContentResolver(), fileName, file.getName(), null);
                    //最后通知图库更新
                    mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + fileName)));
                    shareLocalRes(String.format("file://%s", fileName), shareMsg, "");
                } catch (Exception e) {
                    Log.e(TAG, e.toString());
                }
            }
        }).start();
    }

    /**
     * 分享本地资源到第三方应用
     *
     * @param resUrl 资源本地路径
     * @param msg    文本
     * @param appId  指定应用包名
     */
    private static void shareLocalRes(String resUrl, String msg, String appId) {
        Log.d(TAG, String.format("shareLocalRes resUrl = %s msg = %s appId = %s", resUrl, msg, appId));
        // url = /data/user/0/com.jyyj.hongxiu/files/gamecaches/16434970667499.mp4

        Utils.checkFileUriExposure();
        Uri fileUri;
        File file = new File(resUrl);
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            fileUri = FileProvider.getUriForFile(mContext, mContext.getApplicationContext().getPackageName() + ".JKProvider", file);
            intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, fileUri));
        } else {
            fileUri = Uri.fromFile(file);
        }
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addCategory("android.intent.category.DEFAULT");
        if (fileUri != null)
            intent.putExtra(Intent.EXTRA_STREAM, fileUri);
        intent.putExtra(Intent.EXTRA_SUBJECT, msg);
        intent.putExtra(Intent.EXTRA_TEXT, msg);
        intent.setType("*/*");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);//授权第三方APP可以访问当前的文件
        if (appId != null && appId != "" && appId.length() > 0 && Utils.isInstallApp(mContext, appId)) {
            if (Utils.isInstallApp(mContext, appId)) {

            } else {
                Utils.jumpToAppStore(mContext, appId);
            }
            intent.setPackage(appId);
        } else {
            mContext.startActivity(Intent.createChooser(intent, "Share Local"));
        }
    }

    /**
     * 保存本地或远程到本地相册
     *
     * @param imgUrl 图片地址
     */
    public static void saveImg(String imgUrl) {
        Log.d(TAG, String.format("saveImg imgUrl = %s", imgUrl));
        // url = /data/user/0/com.jyyj.hongxiu/files/gamecaches/16434970667499.mp4

        if (imgUrl.startsWith("http")) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    URL url;
                    Bitmap bitmap;
                    try {
                        url = new URL(imgUrl);
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        //超时设置
                        connection.setConnectTimeout(10 * 1000);
                        connection.setDoInput(true);
                        //设置不使用缓存
                        connection.setUseCaches(false);
                        InputStream inputStream = connection.getInputStream();
                        bitmap = BitmapFactory.decodeStream(inputStream);
                        inputStream.close();
                        connection.disconnect();
                        File file = new File(mContext.getCacheDir().toString());
                        FileOutputStream fileOutputStream;
                        //文件夹不存在，则创建它
                        if (!file.exists()) {
                            file.mkdirs();
                        }
                        String fileName = file.toString() + "/" + System.currentTimeMillis() + ".png";
                        fileOutputStream = new FileOutputStream(fileName);
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
                        fileOutputStream.close();
                        //其次把文件插入到系统图库
                        MediaStore.Images.Media.insertImage(mContext.getContentResolver(), fileName, file.getName(), null);
                        //最后通知图库更新
                        mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + fileName)));
                    } catch (Exception e) {
                        Log.e(TAG, e.toString());
                    }
                }
            }).start();
        } else {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    URL url;
                    Bitmap bitmap;
                    if (isDownloadingUrl) return;
                    isDownloadingUrl = true;
                    try {
                        String fileName = imgUrl;
                        File file;
                        String[] keys = imgUrl.split("/");
                        String simpleName = keys[keys.length - 1].split("\\.")[0];
                        File simpleFile = new File(MediaStore.Images.Media.getContentUri(simpleName).toString());
                        Uri getContentUri = MediaStore.Images.Media.getContentUri(simpleName);
                        if (simpleFile.exists()) return;
                        file = new File(imgUrl);
                        //其次把文件插入到系统图库
                        MediaStore.Images.Media.insertImage(mContext.getContentResolver(), fileName, file.getName(), null);
                        //最后通知图库更新
                        mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + fileName)));
                    } catch (Exception e) {
                        Log.e(TAG, e.toString());
                    }
                    isDownloadingUrl = false;
                }
            }).start();
        }
    }

// =====================================   TalkingData   ===========================================

    /**
     * 初始化 TalkingData
     *
     * @param appContext Application Context
     */
    public static void initTalkingData(Context appContext) {
        Log.d(TAG, "initTalkingData");

        try {
            TalkingDataSDK.init(appContext, SocialConfig.TalkingDataAppId, SocialConfig.TalkingDataChannelId, null);
            TalkingDataSDK.setReportUncaughtExceptions(true);
            TalkingDataSDK.setReportUncaughtExceptions(true);
            TalkingDataProfile mTalkingDataProfile;
            mTalkingDataProfile = mTalkingDataProfile = TalkingDataProfile.createProfile();
            mTalkingDataProfile.setName(SocialConfig.TalkingDataGameService);
            mTalkingDataProfile.setType(TalkingDataProfileType.ANONYMOUS);
            mTalkingDataProfile.setGender(TalkingDataGender.MALE);
            mTalkingDataProfile.setAge(18);
//            mTalkingDataProfile.setProperty1("value1");
//            mTalkingDataProfile.setProperty2("value2");
//            mTalkingDataProfile.setProperty3("value3");
//            mTalkingDataProfile.setProperty4("value4");
//            mTalkingDataProfile.setProperty5("value5");
//            mTalkingDataProfile.setProperty6(0.01);
//            mTalkingDataProfile.setProperty7(99.8);
//            mTalkingDataProfile.setProperty8(100);
//            mTalkingDataProfile.setProperty9(10000);
//            mTalkingDataProfile.setProperty10(100000000000L);
            SharedPreferences sharedPreferences = appContext.getSharedPreferences(SocialConfig.SharePreferenceKey, Context.MODE_PRIVATE);
            String deviceId = sharedPreferences.getString(SocialConfig.TDDeviceKey, "");
            if (deviceId == "") {
                deviceId = TalkingDataSDK.getDeviceId(appContext);
                sharedPreferences.edit().putString(SocialConfig.TDDeviceKey, deviceId);
                TalkingDataSDK.onRegister(deviceId, mTalkingDataProfile, "register123");
            }
            TalkingDataSDK.onLogin(deviceId, mTalkingDataProfile);
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
    }

    // =====================================   FireBase Analytics   ===========================================

    /**
     * 初始化 FireBase Analytics
     *
     * @param appContext Application Context
     */
    @SuppressLint("MissingPermission")
    public static void initFirebaseAnalytics(Context appContext) {
        Log.d(TAG, "initFirebaseAnalytics");

        mFirebaseAnalytics = FirebaseAnalytics.getInstance(mContext);
    }

    /**
     * Google Analytics 打点数据上报
     *
     * @param eventId 事件id
     * @param json    数据对象json字符串
     */
    public static void reportEvent(String eventId, String json) {
        Log.d(TAG, String.format("reportEvent eventId = %s json = %s", eventId, json));

        Bundle bundle = new Bundle();
        Gson gson = new Gson();
        JsonObject obj = gson.fromJson(json, JsonObject.class);
        for (Map.Entry entry : obj.entrySet()) {
            bundle.putString(entry.getKey().toString(), entry.getValue().toString());
        }
        mFirebaseAnalytics.logEvent(eventId, bundle);
    }

    // =====================================   FireBase Remote Config   ===========================================

    /**
     * 初始化 FireBase Remote Config
     */
    public static void initFireBaseRemoteConfig() {
        Log.d(TAG, String.format("initFireBaseRemoteConfig"));

        mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
        FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
                .setMinimumFetchIntervalInSeconds(3600)
                .build();
        mFirebaseRemoteConfig.setConfigSettingsAsync(configSettings);
    }

    /**
     * 获取 FireBase 云控配置数据
     *
     * @param keysJson 键值数组json字符串
     */
    public static void getFireBaseRemoteConfig(String keysJson) {
        Log.d(TAG, String.format("getFireBaseRemoteConfig keysJson = %s", keysJson));

        mFirebaseRemoteConfig.fetchAndActivate()
                .addOnCompleteListener(instance.mActivity, new OnCompleteListener<Boolean>() {
                    @Override
                    public void onComplete(@NonNull Task<Boolean> task) {
                        ArrayList<String> datas = new ArrayList<String>();
                        if (task.isSuccessful()) {
                            Log.d(TAG, String.format("fetchAndActivate success"));

                            Gson gson = new Gson();
                            ArrayList<String> keys = gson.fromJson(keysJson, ArrayList.class);
                            for (String key : keys) {
                                datas.add(mFirebaseRemoteConfig.getString(key));
                            }
                        } else {
                            Log.e(TAG, String.format("fetchAndActivate failed"));
                        }
                        Utils.callCocos2dxJavascript("JKManager && JKManager.onGetFireBaseRemoteConfig && JKManager.onGetFireBaseRemoteConfig(%s)", datas);
                    }
                });
    }

    //========================================================= Google Play Billing ============================================================

    /**
     * 初始话Google Play Billing
     */
    public static void initGooglePlayBilling() {
        Log.d(TAG, String.format("initGooglePlayBilling"));

        // 交易信息更新监听
        PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
            @Override
            public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
                Log.d(TAG, String.format("onPurchasesUpdated"));

                SocialManager.onPurchasesUpdated(billingResult, purchases);
            }
        };
        // 初始化支付客户端
        mBillingClient = BillingClient.newBuilder(mContext)
                .setListener(purchasesUpdatedListener)
                .enablePendingPurchases()
                .build();
        // 链接支付服务器
        mBillingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                int responseCode = billingResult.getResponseCode();
                if (responseCode == BillingClient.BillingResponseCode.OK) {
                    Log.d(TAG, String.format("onBillingSetupFinished success"));
                    // The BillingClient is ready. You can query purchases here.

                    // 每次进行重连的时候都应该查询未处理订单或消耗品
                    // 查询并核销一次性商品订单
                    queryAndConsumePurchase(BillingClient.ProductType.INAPP);
                    // 查询并核销订阅和非消耗型一次性商品订单，且消耗之前缓存的商品，不然可能会导致用户支付不了
                    queryAndConsumePurchase(BillingClient.ProductType.SUBS);
                } else {
                    Log.e(TAG, String.format("onBillingSetupFinished failed responseCode = %d failed", responseCode));
                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                Log.d(TAG, String.format("onBillingServiceDisconnected"));
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
            }
        });

    }

    /**
     * 批量查询指定商品详情
     *
     * @param productIdsJson 商品id
     */
    public static void queryProductDetailsAsync(String productIdsJson) {
        Log.d(TAG, String.format("queryProductDetailsAsync productIdsJson = %s", productIdsJson));

        List<QueryProductDetailsParams.Product> productList = new ArrayList<QueryProductDetailsParams.Product>();
        Gson gson = new Gson();
        List<String> products = gson.fromJson(productIdsJson, List.class);
        for (String productJson : products) {
            GoogeProductData product = gson.fromJson(productJson, GoogeProductData.class);
            productList.add(QueryProductDetailsParams.Product.newBuilder()
                    .setProductId(product.productId)
                    .setProductType(product.productType)
                    .build());
        }
        QueryProductDetailsParams queryProductDetailsParams =
                QueryProductDetailsParams.newBuilder()
                        .setProductList(productList)
                        .build();

        mBillingClient.queryProductDetailsAsync(
                queryProductDetailsParams,
                new ProductDetailsResponseListener() {
                    @Override
                    public void onProductDetailsResponse(@NonNull BillingResult billingResult, @NonNull List<ProductDetails> productDetailsList) {
                        // check BillingResult
                        // process returned ProductDetails list
                        int responseCode = billingResult.getResponseCode();
                        if (responseCode == BillingClient.BillingResponseCode.OK) {
                            Log.d(TAG, String.format("queryProductDetailsAsync onProductDetailsResponse success productDetailsList.size() = %s", productDetailsList.size()));

                            List<ProductDetailsData> productDetailsDatas = new ArrayList<ProductDetailsData>();
                            for (ProductDetails productDetails : productDetailsList) {
                                ProductDetailsData productDetailsData = new ProductDetailsData();
                                productDetailsData.productId = productDetails.getProductId();
                                productDetailsData.productType = productDetails.getProductType();
                                productDetailsData.name = productDetails.getName();
                                productDetailsData.title = productDetails.getTitle();
                                productDetailsData.description = productDetails.getDescription();
                                if (productDetailsData.productType.equals(BillingClient.ProductType.SUBS)) {
                                    productDetailsData.subscriptionOfferDetails = gson.toJson(productDetails.getSubscriptionOfferDetails());
                                } else {
                                    productDetailsData.oneTimePurchaseOfferDetails = gson.toJson(productDetails.getOneTimePurchaseOfferDetails());
                                }
                                productDetailsDatas.add(productDetailsData);
                            }
                            Utils.callCocos2dxJavascript("JKManager && JKManager.onGetProductDetailsAsync && JKManager.onGetProductDetailsAsync(%s)", productDetailsDatas);
                        } else {
                            Log.e(TAG, String.format("queryProductDetailsAsync onProductDetailsResponse failed responseCode = %d failed", responseCode));
                        }
                    }
                }
        );
    }

    /**
     * 购买指定商品
     *
     * @param productId   商品id
     * @param productType 类型
     */
    public static void googlePlayBuy(final String productId, final String productType) {
        instance.mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, String.format("googlePlayBuy productId = %s productType = %s", productId, productType));

                List<QueryProductDetailsParams.Product> productList = new ArrayList<QueryProductDetailsParams.Product>();
                productList.add(QueryProductDetailsParams.Product.newBuilder()
                        .setProductId(productId)
                        .setProductType(productType)
                        .build());
                QueryProductDetailsParams queryProductDetailsParams =
                        QueryProductDetailsParams.newBuilder()
                                .setProductList(productList)
                                .build();

                mBillingClient.queryProductDetailsAsync(
                        queryProductDetailsParams,
                        new ProductDetailsResponseListener() {
                            @Override
                            public void onProductDetailsResponse(@NonNull BillingResult billingResult, @NonNull List<ProductDetails> productDetailsList) {
                                // check BillingResult
                                // process returned ProductDetails list
                                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                                    Log.d(TAG, String.format("googlePlayBuy onProductDetailsResponse success productDetailsList.size() = %s", productDetailsList.size()));

                                    try {
                                        ProductDetails productDetails = productDetailsList.get(0);
                                        List<BillingFlowParams.ProductDetailsParams> productDetailsParamsList = new ArrayList<BillingFlowParams.ProductDetailsParams>();
                                        if (productDetails.getProductType().equals(BillingClient.ProductType.SUBS)) {
                                            List<ProductDetails.SubscriptionOfferDetails> subscriptionOfferDetailsList = productDetails.getSubscriptionOfferDetails();
                                            Log.d(TAG, String.format("googlePlayBuy onProductDetailsResponse success subscriptionOfferDetailsList.size() = %s", subscriptionOfferDetailsList.size()));

                                            productDetailsParamsList.add(BillingFlowParams.ProductDetailsParams.newBuilder()
                                                    // fetched via queryProductDetailsAsync
                                                    .setProductDetails(productDetails)

                                                    // to get an offer token, call ProductDetails.getOfferDetails()
                                                    // for a list of offers that are available to the user
                                                    .setOfferToken(subscriptionOfferDetailsList.get(0).getOfferToken())
                                                    .build());
                                        } else {
                                            productDetailsParamsList.add(BillingFlowParams.ProductDetailsParams.newBuilder()
                                                    // fetched via queryProductDetailsAsync
                                                    .setProductDetails(productDetails)

                                                    // to get an offer token, call ProductDetails.getOfferDetails()
                                                    // for a list of offers that are available to the user
//                                                .setOfferToken(productDetails.getSubscriptionOfferDetails().get(0).getOfferToken())
                                                    .build());
                                        }
                                        BillingFlowParams billingFlowParams =
                                                BillingFlowParams.newBuilder()
                                                        .setProductDetailsParamsList(productDetailsParamsList)
                                                        .build();
                                        int responseCode = mBillingClient.launchBillingFlow(instance.mActivity, billingFlowParams).getResponseCode();
                                        if (responseCode == BillingClient.BillingResponseCode.OK) {
                                            Log.d(TAG, String.format("googlePlayBuy launchBillingFlow success"));
                                        } else {
                                            //BILLING_RESPONSE_RESULT_OK	0	成功
                                            //BILLING_RESPONSE_RESULT_USER_CANCELED	1	用户按上一步或取消对话框
                                            //BILLING_RESPONSE_RESULT_SERVICE_UNAVAILABLE	2	网络连接断开
                                            //BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE	3	所请求的类型不支持 Google Play 结算服务 AIDL 版本
                                            //BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE	4	请求的商品已不再出售
                                            //BILLING_RESPONSE_RESULT_DEVELOPER_ERROR	5	提供给 API 的参数无效。此错误也可能说明应用未针对 Google Play 结算服务正确签名或设置，或者在其清单中缺少必要的权限。
                                            //BILLING_RESPONSE_RESULT_ERROR	6	API 操作期间出现严重错误
                                            //BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED	7	未能购买，因为已经拥有此商品
                                            //BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED	8	未能消费，因为尚未拥有此商品
                                            Log.e(TAG, String.format("googlePlayBuy launchBillingFlow failed responseCode = %s", responseCode));
                                        }
                                    } catch (Exception e) {
                                        Log.e(TAG, String.format("googlePlayBuy launchBillingFlow success %s", e));
                                    }
                                } else {
                                    Log.e(TAG, String.format("googlePlayBuy onProductDetailsResponse failed"));
                                }
                            }
                        }
                );
            }
        });
    }

    /**
     * 订单信息更新
     *
     * @param billingResult
     * @param purchases
     */
    private static void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        Log.d(TAG, String.format("onPurchasesUpdated"));

        int responseCode = billingResult.getResponseCode();
        GooglePlayBuyResult googlePlayBuyResult = new GooglePlayBuyResult();
        if (responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
            Log.d(TAG, String.format("onPurchasesUpdated success"));

            Purchase purchase = purchases.get(0);
            Gson gson = new Gson();
            JsonObject obj = gson.fromJson(purchase.getOriginalJson(), JsonObject.class);
            googlePlayBuyResult.responseCode = responseCode;
            googlePlayBuyResult.productId = obj.get("productId").getAsString();
            handlePurchase(purchase);
        } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
            Log.d(TAG, String.format("onPurchasesUpdated user cancel"));
            // Handle an error caused by a user cancelling the purchase flow.

            googlePlayBuyResult.responseCode = responseCode;
        } else {
            Log.e(TAG, String.format("onPurchasesUpdated failed responseCode = %s", responseCode));
            // Handle any other error codes.

            googlePlayBuyResult.responseCode = responseCode;
        }
        Utils.callCocos2dxJavascript("JKManager && JKManager.onGetProduct && JKManager.onGetProduct(%s)", googlePlayBuyResult);
    }

    /**
     * 处理订单，确认并核销，消耗商品
     *
     * @param purchase 订单
     */
    private static void handlePurchase(Purchase purchase) {
        if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
            if (!purchase.isAcknowledged()) {
                // 如果还没有确认，先确认，在核销
                AcknowledgePurchaseParams acknowledgePurchaseParams =
                        AcknowledgePurchaseParams.newBuilder()
                                .setPurchaseToken(purchase.getPurchaseToken())
                                .build();

                AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = new AcknowledgePurchaseResponseListener() {
                    @Override
                    public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            Log.d(TAG, "handlePurchase onAcknowledgePurchaseResponse success");

                            consumeAsync(purchase);
                        } else {
                            Log.e(TAG, String.format("handlePurchase onAcknowledgePurchaseResponse failed responseCode = %s errorMsg = %s", billingResult.getResponseCode(), billingResult.getDebugMessage()));

                            mHandler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    handlePurchase(purchase);
                                }
                            }, reTryDelayTime);
                        }
                    }
                };

                mBillingClient.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
            } else {
                consumeAsync(purchase);
            }
        }
    }

    /**
     * 核销订单并消耗商品
     *
     * @param purchase 交易订单
     */
    private static void consumeAsync(Purchase purchase) {
        Log.d(TAG, String.format("consumeAsync"));

        // Verify the purchase.
        // Ensure entitlement was not already granted for this purchaseToken.
        // Grant entitlement to the user.

        ConsumeParams consumeParams =
                ConsumeParams.newBuilder()
                        .setPurchaseToken(purchase.getPurchaseToken())
                        .build();

        ConsumeResponseListener listener = new ConsumeResponseListener() {
            @Override
            public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    Log.d(TAG, String.format("consumeAsync onConsumeResponse success"));
                    // Handle the success of the consume operation.
                } else {
                    Log.d(TAG, String.format("consumeAsync onConsumeResponse failed"));

                    if (billingResult.getDebugMessage().contains("Server error, please try again")) {
                        mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                consumeAsync(purchase);
                            }
                        }, reTryDelayTime);
                    }
                }
            }
        };

        mBillingClient.consumeAsync(consumeParams, listener);
    }

    /**
     * 查询未确认或者未核销订单，并核销，查询未消耗的商品，并消耗
     */
    public static void queryAndConsumePurchase(String productType) {
        Log.d(TAG, String.format("queryAndConsumePurchase productType = %s", productType));

        // 查询未确认或者未核销有效订阅和非消耗型一次性订单，并核销
        mBillingClient.queryPurchasesAsync(
                QueryPurchasesParams.newBuilder()
                        .setProductType(productType)
                        .build(),
                new PurchasesResponseListener() {
                    @Override
                    public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> purchaseList) {
                        // check BillingResult
                        // process returned purchase list, e.g. display the plans user owns
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            Log.d(TAG, String.format("queryAndConsumePurchase SUBS onQueryPurchasesResponse success purchaseList.size() = %s", purchaseList.size()));

                            for (Purchase purchase : purchaseList) {
                                handlePurchase(purchase);

                                Gson gson = new Gson();
                                JsonObject obj = gson.fromJson(purchase.getOriginalJson(), JsonObject.class);
                                GooglePlayBuyResult queryPurchasesResult = new GooglePlayBuyResult();
                                queryPurchasesResult.responseCode = -1;
                                queryPurchasesResult.productId = obj.get("productId").getAsString();
                                Utils.callCocos2dxJavascript("JKManager && JKManager.onGetProduct && JKManager.onGetProduct(%s)", queryPurchasesResult);
                            }
                        } else {
                            Log.e(TAG, String.format("queryAndConsumePurchase SUBS onQueryPurchasesResponse failed"));

//                            mHandler.postDelayed(new Runnable() {
//                                @Override
//                                public void run() {
//                                    queryAndConsumePurchase(productType);
//                                }
//                            }, reTryDelayTime);
                        }
                    }
                }
        );

        // 查询每个商品发起的最近一笔购买记录，并消耗商品，即使该购买交易已过期、已取消或已消耗
        mBillingClient.queryPurchaseHistoryAsync(
                QueryPurchaseHistoryParams.newBuilder()
                        .setProductType(productType)
                        .build(),
                new PurchaseHistoryResponseListener() {
                    @Override
                    public void onPurchaseHistoryResponse(@NonNull BillingResult billingResult, @Nullable List<PurchaseHistoryRecord> purchaseHistoryRecordList) {
                        // check BillingResult
                        // process returned purchase history list, e.g. display purchase history
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            Log.d(TAG, String.format("onPurchaseHistoryResponse SUBS onPurchaseHistoryResponse success purchaseHistoryRecordList.size() = %s", purchaseHistoryRecordList.size()));

                            for (PurchaseHistoryRecord purchaseHistoryRecord : purchaseHistoryRecordList) {
                                Purchase purchase = null;
                                try {
                                    purchase = new Purchase(purchaseHistoryRecord.getOriginalJson(), purchaseHistoryRecord.getSignature());
                                    handlePurchase(purchase);
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                            }
                        } else {
                            Log.e(TAG, String.format("queryAndConsumePurchase SUBS onQueryPurchasesResponse failed"));

//                            mHandler.postDelayed(new Runnable() {
//                                @Override
//                                public void run() {
//                                    queryAndConsumePurchase(productType);
//                                }
//                            }, reTryDelayTime);
                        }
                    }
                }
        );
    }

    /**
     * 查询有效订阅和非消耗型一次性购买交易
     */
    public static void googlePlayQueryPurchasesAsync() {
        Log.d(TAG, String.format("googlePlayQueryPurchasesAsync"));

        SocialManager.onQueryPurchasesResponseCnt = 0;
        mBillingClient.queryPurchasesAsync(
                QueryPurchasesParams.newBuilder()
                        .setProductType(BillingClient.ProductType.SUBS)
                        .build(),
                new PurchasesResponseListener() {
                    @Override
                    public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> purchaseList) {
                        // check BillingResult
                        // process returned purchase list, e.g. display the plans user owns
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            Log.d(TAG, String.format("googlePlayQueryPurchasesAsync SUBS onQueryPurchasesResponse1 success purchaseList.size() = %s", purchaseList.size()));

                            for (Purchase purchase : purchaseList) {
                                handlePurchase(purchase);

                                Gson gson = new Gson();
                                JsonObject obj = gson.fromJson(purchase.getOriginalJson(), JsonObject.class);
                                GooglePlayBuyResult queryPurchasesResult = new GooglePlayBuyResult();
                                queryPurchasesResult.responseCode = -1;
                                queryPurchasesResult.productId = obj.get("productId").getAsString();
                                Utils.callCocos2dxJavascript("JKManager && JKManager.onGetProduct && JKManager.onGetProduct(%s)", queryPurchasesResult);
                            }
                            if (purchaseList.size() == 0) {
                                SocialManager.onQueryPurchasesResponseCnt++;
                                if (SocialManager.onQueryPurchasesResponseCnt == 2) {
                                    Gson gson = new Gson();
                                    GooglePlayBuyResult queryPurchasesResult = new GooglePlayBuyResult();
                                    queryPurchasesResult.responseCode = -1;
                                    queryPurchasesResult.productId = "NONE";
                                    Utils.callCocos2dxJavascript("JKManager && JKManager.onGetProduct && JKManager.onGetProduct(%s)", queryPurchasesResult);
                                }
                            }
                        } else {
                            Log.e(TAG, String.format("googlePlayQueryPurchasesAsync SUBS onQueryPurchasesResponse1 failed"));

//                            mHandler.postDelayed(new Runnable() {
//                                @Override
//                                public void run() {
//                                    SocialManager.googlePlayQueryPurchasesAsync();
//                                }
//                            }, reTryDelayTime);
                        }
                    }
                }
        );
        mBillingClient.queryPurchasesAsync(
                QueryPurchasesParams.newBuilder()
                        .setProductType(BillingClient.ProductType.INAPP)
                        .build(),
                new PurchasesResponseListener() {
                    @Override
                    public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> purchaseList) {
                        // check BillingResult
                        // process returned purchase list, e.g. display the plans user owns
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            Log.d(TAG, String.format("googlePlayQueryPurchasesAsync SUBS onQueryPurchasesResponse2 success purchaseList.size() = %s", purchaseList.size()));

                            for (Purchase purchase : purchaseList) {
                                handlePurchase(purchase);

                                Gson gson = new Gson();
                                JsonObject obj = gson.fromJson(purchase.getOriginalJson(), JsonObject.class);
                                GooglePlayBuyResult queryPurchasesResult = new GooglePlayBuyResult();
                                queryPurchasesResult.responseCode = -1;
                                queryPurchasesResult.productId = obj.get("productId").getAsString();
                                Utils.callCocos2dxJavascript("JKManager && JKManager.onGetProduct && JKManager.onGetProduct(%s)", queryPurchasesResult);
                            }
                            if (purchaseList.size() == 0) {
                                SocialManager.onQueryPurchasesResponseCnt++;
                                if (SocialManager.onQueryPurchasesResponseCnt == 2) {
                                    Gson gson = new Gson();
                                    GooglePlayBuyResult queryPurchasesResult = new GooglePlayBuyResult();
                                    queryPurchasesResult.responseCode = -1;
                                    queryPurchasesResult.productId = "NONE";
                                    Utils.callCocos2dxJavascript("JKManager && JKManager.onGetProduct && JKManager.onGetProduct(%s)", queryPurchasesResult);
                                }
                            }
                        } else {
                            Log.e(TAG, String.format("googlePlayQueryPurchasesAsync SUBS onQueryPurchasesResponse2 failed"));

//                            mHandler.postDelayed(new Runnable() {
//                                @Override
//                                public void run() {
//                                    SocialManager.googlePlayQueryPurchasesAsync();
//                                }
//                            }, reTryDelayTime);
                        }
                    }
                }
        );
    }

    /**
     * 查询用户针对每个商品发起的最近一笔购买记录，即使该购买交易已过期、已取消或已消耗，也仍会提取相关记录
     */
    public static void googlePlayQueryPurchaseHistoryAsync() {
        Log.d(TAG, String.format("googlePlayQueryPurchaseHistoryAsync"));

        mBillingClient.queryPurchaseHistoryAsync(
                QueryPurchaseHistoryParams.newBuilder()
                        .setProductType(BillingClient.ProductType.SUBS)
                        .build(),
                new PurchaseHistoryResponseListener() {
                    @Override
                    public void onPurchaseHistoryResponse(@NonNull BillingResult billingResult, @Nullable List<PurchaseHistoryRecord> purchaseHistoryRecordList) {
                        // check BillingResult
                        // process returned purchase history list, e.g. display purchase history
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            Log.d(TAG, String.format("googlePlayQueryPurchaseHistoryAsync SUBS onPurchaseHistoryResponse success purchaseHistoryRecordList.size() = %s", purchaseHistoryRecordList.size()));

                            for (PurchaseHistoryRecord purchaseHistoryRecord : purchaseHistoryRecordList) {
                                Purchase purchase = null;
                                try {
                                    purchase = new Purchase(purchaseHistoryRecord.getOriginalJson(), purchaseHistoryRecord.getSignature());

                                    Utils.callCocos2dxJavascript("JKManager && JKManager.onGetPurchaseHistoryAsync && JKManager.onGetPurchaseHistoryAsync(%s)", purchase.getOriginalJson());
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                            }
                        } else {
                            Log.e(TAG, String.format("googlePlayQueryPurchaseHistoryAsync SUBS onQueryPurchasesResponse failed"));

                            mHandler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    queryAndConsumePurchase(BillingClient.ProductType.SUBS);
                                }
                            }, reTryDelayTime);
                        }
                    }
                }
        );
        mBillingClient.queryPurchaseHistoryAsync(
                QueryPurchaseHistoryParams.newBuilder()
                        .setProductType(BillingClient.ProductType.INAPP)
                        .build(),
                new PurchaseHistoryResponseListener() {
                    @Override
                    public void onPurchaseHistoryResponse(@NonNull BillingResult billingResult, @Nullable List<PurchaseHistoryRecord> purchaseHistoryRecordList) {
                        // check BillingResult
                        // process returned purchase history list, e.g. display purchase history
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            Log.d(TAG, String.format("googlePlayQueryPurchaseHistoryAsync SUBS onPurchaseHistoryResponse success purchaseHistoryRecordList.size() = %s", purchaseHistoryRecordList.size()));

                            for (PurchaseHistoryRecord purchaseHistoryRecord : purchaseHistoryRecordList) {
                                Purchase purchase = null;
                                try {
                                    purchase = new Purchase(purchaseHistoryRecord.getOriginalJson(), purchaseHistoryRecord.getSignature());

                                    Utils.callCocos2dxJavascript("JKManager && JKManager.onGetPurchaseHistoryAsync && JKManager.onGetPurchaseHistoryAsync(%s)", purchase.getOriginalJson());
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                            }
                        } else {
                            Log.e(TAG, String.format("googlePlayQueryPurchaseHistoryAsync SUBS onQueryPurchasesResponse failed"));

                            mHandler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    queryAndConsumePurchase(BillingClient.ProductType.INAPP);
                                }
                            }, reTryDelayTime);
                        }
                    }
                }
        );
    }

    //========================================================= Applovin MAX ============================================================

    /**
     * 初始化广告
     */
    public static void initAd() {
        Log.d(TAG, String.format("initAd"));

        instance.mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    Class.forName(MAXAdapter.class.getName());
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
                AdManager.ins().initAd(instance.mActivity, "appKey");
            }
        });
    }

    /**
     * 显示横幅广告
     */
    public static void showBanner() {
        Log.d(TAG, String.format("showBanner"));

        instance.mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (AdManager.ins().isBannerReady()) {
                    AdManager.ins().showBanner(new AdManager.AdCallBack() {
                        @Override
                        public void onStart(JSONObject ret) {
                            Log.d(TAG, String.format("showBanner onStart"));
                        }

                        @Override
                        public void onFinish(JSONObject ret) {
                            Log.d(TAG, String.format("showBanner onFinish"));

                            try {
                                boolean isFullWatch = ret.getBoolean("Status");
                                Utils.callCocos2dxJavascript("JKManager && JKManager.onBannerAdFinished && JKManager.onBannerAdFinished(%s)", isFullWatch ? "Finished" : "UnFinished");
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onClick(JSONObject ret) {
                            Log.d(TAG, String.format("showBanner onClick"));
                        }
                    });
                } else {
                    Utils.callCocos2dxJavascript("JKManager && JKManager.onInterAdFinished && JKManager.onBannerAdFinished(`NotReady`)");
                }
            }
        });
    }

    /**
     * 隐藏横幅广告
     */
    public static void hideBanner() {
        Log.d(TAG, String.format("hideBanner"));

        instance.mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                AdManager.ins().hideBanner();
            }
        });
    }

    /**
     * 显示插屏广告
     */
    public static void showInter() {
        Log.d(TAG, String.format("showInter"));

        instance.mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (AdManager.ins().isInterReady()) {
                    AdManager.ins().showInter(null, new AdManager.AdCallBack() {
                        @Override
                        public void onStart(JSONObject ret) {
                            Log.d(TAG, String.format("showInter onStart"));
                        }

                        @Override
                        public void onFinish(JSONObject ret) {
                            Log.d(TAG, String.format("showInter onFinish"));

//                            try {
//                                boolean isFullWatch = ret.getBoolean("Status");
                            Utils.callCocos2dxJavascript("JKManager && JKManager.onInterAdFinished && JKManager.onInterAdFinished(`%s`)", "Finished");
//                            } catch (JSONException e) {
//                                e.printStackTrace();
//                            }
                        }

                        @Override
                        public void onClick(JSONObject ret) {
                            Log.d(TAG, String.format("showInter onClick"));
                        }
                    });
                } else {
                    Utils.callCocos2dxJavascript("JKManager && JKManager.onInterAdFinished && JKManager.onInterAdFinished(`NotReady`)");
                }
            }
        });
    }

    /**
     * 显示激励广告
     */
    public static void showVideo() {
        Log.d(TAG, String.format("showVideo"));

        instance.mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (AdManager.ins().isVideoReady()) {
                    AdManager.ins().showVideo(null, new AdManager.AdCallBack() {
                        @Override
                        public void onStart(JSONObject ret) {
                            Log.d(TAG, String.format("showVideo onStart"));
                        }

                        @Override
                        public void onFinish(JSONObject ret) {
                            Log.d(TAG, String.format("showVideo onFinish"));

                            try {
                                boolean isFullWatch = ret.getBoolean("Status");
                                Utils.callCocos2dxJavascript("JKManager && JKManager.onVideoAdFinished && JKManager.onVideoAdFinished(`%s`)", isFullWatch ? "Finished" : "UnFinished");
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onClick(JSONObject ret) {
                            Log.d(TAG, String.format("showVideo onClick"));
                        }
                    });
                } else {
                    Utils.callCocos2dxJavascript("JKManager && JKManager.onVideoAdFinished && JKManager.onVideoAdFinished(`NotReady`)");
                }
            }
        });
    }
}

class GoogeProductData {
    @JsonProperty("productId")
    public String productId;
    @JsonProperty("productType")
    public String productType;
}

class ProductDetailsData {
    @JsonProperty("productId")
    public String productId;
    @JsonProperty("productType")
    public String productType;
    @JsonProperty("title")
    public String title;
    @JsonProperty("name")
    public String name;
    @JsonProperty("description")
    public String description;
    @JsonProperty("oneTimePurchaseOfferDetails")
    public String oneTimePurchaseOfferDetails;
    @JsonProperty("subscriptionOfferDetails")
    public String subscriptionOfferDetails;
}

class GooglePlayBuyResult {
    @JsonProperty("responseCode")
    public int responseCode;
    @JsonProperty("productId")
    public String productId;
}